package com.hbjycl.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.hbjycl.dao.BaseDao;


/**
 * 基础Dao实现
 * 
 * @author wxp
 *
 * @datetime 2014年8月13日下午3:42:07
 */
@Repository
public class BaseDaoImpl<T, PK extends Serializable> implements BaseDao<T, PK>
{
    private Class<T>         entityClass;
    @Resource
    protected SessionFactory sessionFactory;
    
    @SuppressWarnings("unchecked")
    public BaseDaoImpl()
    {
        this.entityClass = null;
        Class c = getClass();
        Type type = c.getGenericSuperclass();
        if (type instanceof ParameterizedType)
        {
            Type [] parameterizedType = ((ParameterizedType) type).getActualTypeArguments();
            this.entityClass = (Class<T>) parameterizedType[0];
        }
    }
    
    protected Session getSession()
    {
        return this.sessionFactory.getCurrentSession();
    }
    
    @SuppressWarnings("unchecked")
    public T get(PK id)
    {
        Assert.notNull(id, "id is required");
        return (T) getSession().get(entityClass, id);
    }
    
    @SuppressWarnings("unchecked")
    public T load(PK id)
    {
        Assert.notNull(id, "id is required");
        return (T) getSession().load(entityClass, id);
    }
    
    @SuppressWarnings("unchecked")
    public List<T> get(PK [] ids)
    {
        Assert.notEmpty(ids, "ids must not empty");
        String hql = "from " + entityClass.getName() + " where id in(:ids)";
        return getSession().createQuery(hql).setParameterList("ids", ids).list();
    }
    
    @SuppressWarnings("unchecked")
    public T get(String propertyName, Object value)
    {
        Assert.hasText(propertyName, "propertyName must not be empty");
        Assert.notNull(value, "value is required");
        String hql = "from " + entityClass.getName() + " as model where model." + propertyName
                + " = ?";
        return (T) getSession().createQuery(hql).setParameter(0, value).uniqueResult();
    }
    
    @SuppressWarnings("unchecked")
    public List<T> getList(String propertyName, Object value)
    {
        Assert.hasText(propertyName, "propertyName must not be empty");
        Assert.notNull(value, "value is required");
        String hql = "from " + entityClass.getName() + " as model where model." + propertyName
                + " = ?";
        return getSession().createQuery(hql).setParameter(0, value).list();
    }
    
    @SuppressWarnings("unchecked")
    public List<T> getAll()
    {
        String hql = "from " + entityClass.getName();
        return getSession().createQuery(hql).list();
    }
    
    public Long getTotalCount()
    {
        String hql = "select count(*) from " + entityClass.getName();
        return (Long) getSession().createQuery(hql).uniqueResult();
    }
    
    public boolean isUnique(String propertyName, Object oldValue, Object newValue)
    {
        Assert.hasText(propertyName, "propertyName must not be empty");
        Assert.notNull(newValue, "newValue is required");
        
        if (newValue == oldValue || newValue.equals(oldValue))
        {
            return true;
        }
        
        if (newValue instanceof String)
        {
            if (oldValue != null
                    && StringUtils.equalsIgnoreCase((String) oldValue, (String) newValue))
            {
                return true;
            }
        }
        T object = get(propertyName, newValue);
        return (object == null);
    }
    
    public boolean isExist(String propertyName, Object value)
    {
        Assert.hasText(propertyName, "propertyName must not be empty");
        Assert.notNull(value, "value is required");
        T object = get(propertyName, value);
        return (object != null);
    }
    
    @SuppressWarnings("unchecked")
    public PK save(T entity)
    {
        Assert.notNull(entity, "entity is required");
        return (PK) getSession().save(entity);
    }
    
    public void update(T entity)
    {
        Assert.notNull(entity, "entity is required");
        getSession().update(entity);
    }
    
    public void delete(T entity)
    {
        Assert.notNull(entity, "entity is required");
        getSession().delete(entity);
    }
    
    public void delete(PK id)
    {
        Assert.notNull(id, "id is required");
        T entity = load(id);
        getSession().delete(entity);
    }
    
    public void delete(PK [] ids)
    {
        Assert.notEmpty(ids, "ids must not be empty");
        for (PK id : ids)
        {
            T entity = load(id);
            getSession().delete(entity);
        }
    }
    
    public void flush()
    {
        getSession().flush();
    }
    
    public void clear()
    {
        getSession().clear();
    }
    
    public void evict(Object object)
    {
        Assert.notNull(object, "object is required");
        getSession().evict(object);
    }
    

    
}
